package com.huatai.model.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huatai.model.mapper.BaseMapperAmy;


import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author Lion
 * @date 2023/6/2  9:51
 */
public class BaseService<M extends BaseMapperAmy<T>,T> extends ServiceImpl<M,T> {

	/**
	 * 构造数据的扩展信息,空方法，继承后实现
	 *
	 * @param datas
	 * @return
	 */
	public List<T> buildExInfo(List<T> datas) {
		return datas;
	}

	/**
	 * 保存数据,保存前对数据进行Validation校验(当ID存在时，则更新，否则新增)
	 * 由于没有使用到事务，所以查询后再保存，整个动作耗时较短
	 */
	public boolean SaveOrUpdateWithValid(T data) {
		//保存数据
		TableInfo tableInfo = TableInfoHelper.getTableInfo(data.getClass());
		String keyProperty = tableInfo.getKeyProperty();
		Object idVal = BeanUtil.getFieldValue(data, keyProperty);
		if (ObjectUtil.isEmpty(idVal) || ObjectUtil.isNull(getById((Serializable) idVal))) {
			SaveWithValid(data);
		} else {
			UpdateWithValid(data);
		}
		return true;
	}

	/**
	 * 保存数据,保存前对数据进行Validation校验(当ID存在时，则更新，否则新增)
	 */
	public boolean SaveWithValid(T data) {
		//保存数据
		//ValidatedUtils.validateWithThrow(data, T.ValidGroup_Add.class);
		super.save(data);
		return true;
	}

	/**
	 * 保存数据,保存前对数据进行Validation校验(当ID存在时，则更新，否则新增)
	 */
	public boolean UpdateWithValid(T data) {
		//保存数据
		TableInfo tableInfo = TableInfoHelper.getTableInfo(data.getClass());
		Assert.notNull(tableInfo, "can not execute. because can not find cache of TableInfo for entity!");
		String keyProperty = tableInfo.getKeyProperty();
		Assert.notEmpty(keyProperty, " can not execute. because can not find column for id from entity!");
		Object idVal = BeanUtil.getFieldValue(data, keyProperty);
		//AssertI.notEmpty(idVal, "can not execute. because pk value is null or empty");

		if (ObjectUtil.isNull(getById((Serializable) idVal))) {
			//throw new AmyAppException("记录[ID:{}]不存在，无法更新", idVal);
			//抛出异常
		}
		super.updateById(data);
		return true;
	}


	/**
	 * 从map的key-value中生成Pageable对象
	 *
	 * @param index 当前索引页，其中1表示第一页
	 * @param size  每页大小
	 * @return
	 */
	public IPage buildPage(int index, int size) {
		index = index < 1 ? 1 : index;
		size = size < 1 ? 10 : size;
		return new Page<T>(index, size);
	}

	/**
	 * 从map的key-value中生成Pageable对象
	 *
	 * @param map 1 表示第一页
	 * @return
	 */
	public IPage buildPage(Map<String, Object> map) {
		int index = 0;
		int size = 10;
		if (map != null && map.size() > 0) {
			index = Integer.valueOf(map.getOrDefault("pageIndex", 1).toString());
			index = index < 1 ? 1 : index;
			size = Integer.valueOf(map.getOrDefault("pageSize", 10).toString());
			size = size < 1 ? 10 : size;
		}
		return buildPage(index, size);
	}

	/**
	 * 获取分页数据
	 *
	 * @return
	 */
	public IPage<T> pageByRequestMap(Map map) {
		//构建QueryWrapper

		QueryWrapper qw = this.buildQW(map);
		IPage<T> page = this.buildPage(map);
		return this.page(page, qw);
	}

	/**
	 * @author Lion
	 * @description 构造查询条件
	 * @param  * @param map
	 * @return com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<T>
	 */
	public QueryWrapper<T> buildQW(Map<String, Object> map) {
		QueryWrapper<T> qw = new QueryWrapper<T>();
		if (ObjectUtil.isEmpty(map)) {
			return qw;
		}
		//先设置排序
		String order = map.getOrDefault("or_orderby", "").toString();
		if (StrUtil.isNotBlank(order) && !order.equalsIgnoreCase(":")) {
			//orderby 格式为:字段1,字段2:ASC或DSC
			String[] orders = StrUtil.split(order, ':', true, true).toArray(new String[0]);
			if (orders.length > 0) {
				String orderType = orders.length == 2 ? orders[1].toUpperCase() : "ASC";
				String[] orderColumns = StrUtil.split(orders[0], ',', true, true).toArray(new String[0]);
				qw.orderBy(true, orderType.equals("ASC"), String.valueOf(orderColumns));
			}
		}

		Boolean isAnd = "AND".equalsIgnoreCase(map.getOrDefault("join_type", "AND").toString());
		for (Map.Entry<String, Object> entry : map.entrySet()) {
			String queryKey = entry.getKey();
			String columnName = "";

			String columnValue = isEmpty(entry.getValue()) ? "" : entry.getValue().toString();
			// 跳出不满足条件的参数
			if (!queryKey.startsWith("sk_")
				|| StrUtil.isBlank(columnValue)
				|| columnValue.equals("[]")) {
				continue;
			}
			//like
			if (StrUtil.startWith(queryKey, "sk_like_")) {
				columnName = StrUtil.removePrefix(queryKey, "sk_like_");
				if (isAnd) {
					qw.like(columnName, columnValue);
				} else {
					qw.or().like(columnName, columnValue);
				}
				continue;
			}
			//notlike
			if (StrUtil.startWith(queryKey, "sk_notlike_")) {
				columnName = StrUtil.removePrefix(queryKey, "sk_notlike_");
				if (isAnd) {
					qw.notLike(columnName, columnValue);
				} else {
					qw.or().notLike(columnName, columnValue);
				}
				continue;
			}
			//equal
			if (StrUtil.startWith(queryKey, "sk_equal_")) {
				columnName = StrUtil.removePrefix(queryKey, "sk_equal_");
				if (isAnd) {
					qw.eq(columnName, columnValue);
				} else {
					qw.or().eq(columnName, columnValue);
				}
				continue;
			}
			//notequal
			if (StrUtil.startWith(queryKey, "sk_notequal_")) {
				columnName = StrUtil.removePrefix(queryKey, "sk_notequal_");
				if (isAnd) {
					qw.ne(columnName, columnValue);
				} else {
					qw.or().ne(columnName, columnValue);
				}
				continue;
			}
		}
		return qw;
	}

	/**
	 * @author Lion
	 * @description 判断对象是否为空
	 * @param  * @param obj
	 * @return boolean
	 */
	public static boolean isEmpty(Object obj) {
		if (null == obj) {
			return true;
		} else if (obj instanceof CharSequence) {
			return StrUtil.isEmpty((CharSequence)obj);
		} else if (obj instanceof Map) {
			return MapUtil.isEmpty((Map)obj);
		} else if (obj instanceof Iterable) {
			return IterUtil.isEmpty((Iterable)obj);
		} else if (obj instanceof Iterator) {
			return IterUtil.isEmpty((Iterator)obj);
		} else {
			return ArrayUtil.isArray(obj) ? ArrayUtil.isEmpty(obj) : false;
		}
	}



}
